package com.example.shuma_product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.shuma_product.dao.entity.ManagerDO;
import com.example.shuma_product.dao.mapper.ManagerMapper;
import com.example.shuma_product.dto.rep.ManagerLoginReqDTO;
import com.example.shuma_product.dto.rep.ManagerRegisterRepDTO;
import com.example.shuma_product.dto.resp.ManagerLoginRespDTO;
import com.example.shuma_product.errorcode.BaseErrorCode;
import com.example.shuma_product.exception.ClientException;
import com.example.shuma_product.service.ManagerService;
import com.example.shuma_product.utils.JwtUtils;
import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

import static com.example.shuma_product.errorcode.BaseErrorCode.SERVICE_ERROR;
import static com.example.shuma_product.errorcode.BaseErrorCode.USER_EXIST;

@Service
public class ManagerServiceImpl extends ServiceImpl<ManagerMapper, ManagerDO> implements ManagerService{

    @Autowired
    private  RBloomFilter<String> userRegisterCachePenetrationBloomFilter;  //注入布隆过滤器
    @Autowired
    private  RedissonClient redissonClient;
    @Autowired
    private  StringRedisTemplate redisTemplate;    //注入redis模板类

    @Override
    public Boolean hasUsername(String username) {
        return !userRegisterCachePenetrationBloomFilter.contains(username);
    }

    @Override
    public void register(ManagerRegisterRepDTO requestParam) {

        //1.先判断用户名是否已存在
        if(!hasUsername(requestParam.getUsername())){
            throw new ClientException(USER_EXIST);
        }

        //2.获取分布式锁，锁住用户名，防止海量用户注册同一个用户名
        RLock lock = redissonClient.getLock(requestParam.getUsername());
        try {
            if(lock.tryLock()){
                requestParam.setManagerRole("普通管理员");
                int insert = baseMapper.insert(BeanUtil.toBean(requestParam, ManagerDO.class));
                if(insert<1){
                    throw new ClientException(SERVICE_ERROR);
                }
                //把用户名添加到布隆过滤器
                userRegisterCachePenetrationBloomFilter.add(requestParam.getUsername());
                return;
            }
            throw new ClientException(USER_EXIST);
        }finally {
            lock.unlock();
        }
    }

    @Override
    public ManagerLoginRespDTO login(ManagerLoginReqDTO requestParam) {
        LambdaQueryWrapper<ManagerDO> eq = Wrappers.lambdaQuery(ManagerDO.class)
                .eq(ManagerDO::getUsername, requestParam.getUsername())
                .eq(ManagerDO::getPassword, requestParam.getPassword());
        ManagerDO managerDO = baseMapper.selectOne(eq);

        if(managerDO == null){
            throw new ClientException("账号或密码错误");
        }


        Map<String, Object> claims = new HashMap<>();
        claims.put("ManagerId",managerDO.getManagerId());
        claims.put("username",managerDO.getUsername());
        //生成JWT令牌,在令牌中存入管理员的id和名字
        String jwt = JwtUtils.genJwt(claims);

        ManagerLoginRespDTO managerLoginRespDTO = ManagerLoginRespDTO.builder()
                .jwt(jwt)
                .managerRole(managerDO.getManagerRole())
                .build();
        return managerLoginRespDTO;
    }
}
